﻿using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.ApplicationServices; // 需要 Application
using System;
using System.IO;
using System.Linq;
using System.Diagnostics;

namespace RevitProject.SpaceManager.Helper 
{
    /// <summary>
    /// 用于处理共享参数创建和绑定的辅助类。
    /// 适配 Revit 2021 及更高版本的 API (使用 ForgeTypeId)。
    /// </summary>
    public static class SharedParameterHelper
    {
        // ****** 定义共享参数的常量 ******
        private static readonly Guid SharedParameterGuid = new Guid("5d906d90-c5da-45e1-a98b-c34acb5373d5"); // 您提供的 GUID
        public const string SharedParameterName = "空间类别"; // 参数名称
        public const string SharedParameterGroupName = "自定义参数"; // 共享参数文件中的分组名称
        private static readonly BuiltInCategory TargetCategory = BuiltInCategory.OST_Rooms; // 目标 Revit 类别

        // ****** 修改：使用 GroupTypeId 定义属性面板分组 ******
        
        private static readonly ForgeTypeId ParameterGroupInUI = GroupTypeId.IdentityData; // 新代码 (需要 using Autodesk.Revit.DB;)

        // 使用 ForgeTypeId 定义参数的数据类型
        private static readonly ForgeTypeId ParameterDataTypeSpec = SpecTypeId.String.Text; // 数据类型为文本

        /// <summary>
        /// 确保指定的共享参数存在于共享参数文件中，并已作为实例参数绑定到目标类别 (OST_Rooms)。
        /// </summary>
        /// <param name="app">Revit Application 对象。</param>
        /// <param name="doc">当前的 Revit Document 对象。</param>
        /// <returns>成功确保参数存在并绑定时返回 ExternalDefinition，否则返回 null。</returns>
        public static ExternalDefinition EnsureParameterExistsAndBound(Application app, Document doc)
        {
            if (app == null)
            {
                Debug.WriteLine("EnsureParameterExistsAndBound 错误: Application 对象为空。");
                TaskDialog.Show("错误", "Revit Application 对象无效。");
                return null;
            }
            if (doc == null || !doc.IsValidObject)
            {
                Debug.WriteLine("EnsureParameterExistsAndBound 错误: Document 对象为空或无效。");
                TaskDialog.Show("错误", "Revit Document 对象无效。");
                return null;
            }

            try
            {
                DefinitionFile sharedParamFile = GetOrCreateSharedParameterFile(app);
                if (sharedParamFile == null) return null;

                DefinitionGroup group = GetOrCreateDefinitionGroup(sharedParamFile, SharedParameterGroupName);
                if (group == null) return null;

                ExternalDefinition definition = GetOrCreateParameterDefinition(group, SharedParameterName, ParameterDataTypeSpec);
                if (definition == null) return null;

                if (!IsParameterBound(doc, definition))
                {
                    Debug.WriteLine($"参数 '{SharedParameterName}' 未绑定到类别 '{TargetCategory}'。尝试绑定...");
                    if (!BindParameterToCategory(doc, app, definition, TargetCategory))
                    {
                        return null; // 绑定失败
                    }
                    if (!IsParameterBound(doc, definition))
                    {
                        TaskDialog.Show("绑定问题", $"尝试绑定共享参数 '{SharedParameterName}' 后未能确认绑定成功。");
                        return null;
                    }
                    else
                    {
                        Debug.WriteLine($"参数 '{SharedParameterName}' 成功绑定到类别 '{TargetCategory}'。");
                    }
                }
                else
                {
                    Debug.WriteLine($"参数 '{SharedParameterName}' 已绑定到类别 '{TargetCategory}'。");
                }

                return definition;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"EnsureParameterExistsAndBound 过程中发生意外错误: {ex.ToString()}");
                TaskDialog.Show("严重错误", $"处理共享参数 '{SharedParameterName}' 时发生意外错误:\n{ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 获取或创建共享参数文件。
        /// </summary>
        private static DefinitionFile GetOrCreateSharedParameterFile(Application app)
        {
            try
            {
                string filePath = app.SharedParametersFilename;
                if (string.IsNullOrEmpty(filePath))
                {
                    TaskDialog.Show("需要操作", "Revit 未设置共享参数文件路径。\n\n请在 Revit 的“管理”选项卡 -> “共享参数”中指定一个文件路径。");
                    return null;
                }
                if (!File.Exists(filePath))
                {
                    TaskDialog.Show("文件未找到", $"指定的共享参数文件不存在: \n{filePath}\n\n请检查路径或重新指定。");
                    return null;
                }
                var defFile = app.OpenSharedParameterFile();
                if (defFile == null)
                {
                    TaskDialog.Show("错误", $"无法打开指定的共享参数文件: \n{filePath}\n\n请检查文件是否被其他程序占用或权限是否正确。");
                    return null;
                }
                return defFile;
            }
            catch (Autodesk.Revit.Exceptions.InvalidOperationException ioEx)
            {
                TaskDialog.Show("Revit 操作错误", $"访问共享参数文件时发生 Revit 内部错误: {ioEx.Message}\n\n请确认共享参数文件配置正确。");
                Debug.WriteLine($"GetOrCreateSharedParameterFile Revit InvalidOperationException: {ioEx}");
                return null;
            }
            catch (Exception ex)
            {
                TaskDialog.Show("错误", $"访问共享参数文件时发生错误: {ex.Message}");
                Debug.WriteLine($"GetOrCreateSharedParameterFile Exception: {ex}");
                return null;
            }
        }

        /// <summary>
        /// 获取或创建共享参数分组。
        /// </summary>
        private static DefinitionGroup GetOrCreateDefinitionGroup(DefinitionFile file, string groupName)
        {
            if (file == null || string.IsNullOrWhiteSpace(groupName))
            {
                Debug.WriteLine($"GetOrCreateDefinitionGroup 错误: 输入无效 (文件: {file == null}, 组名: '{groupName}')");
                return null;
            }
            try
            {
                DefinitionGroup group = file.Groups.get_Item(groupName);
                if (group == null)
                {
                    group = file.Groups.Create(groupName);
                    Debug.WriteLine($"在共享参数文件中创建了新的分组: '{groupName}'");
                }
                return group;
            }
            catch (Exception ex)
            {
                TaskDialog.Show("错误", $"处理共享参数分组 '{groupName}' 时出错: {ex.Message}");
                Debug.WriteLine($"GetOrCreateDefinitionGroup Exception: {ex}");
                return null;
            }
        }

        /// <summary>
        /// 获取或创建共享参数定义。
        /// </summary>
        private static ExternalDefinition GetOrCreateParameterDefinition(DefinitionGroup group, string paramName, ForgeTypeId paramDataTypeSpec)
        {
            // 检查输入参数是否有效
            // ****** 修改这里：仅保留 null 检查 ******
            if (group == null || string.IsNullOrWhiteSpace(paramName) || paramDataTypeSpec == null) // <-- 移除关于 Equals 的部分
            {
                // TaskDialog 和 Debug.WriteLine 保持不变
                TaskDialog.Show("错误", "获取或创建参数定义时输入无效 (组、名称或数据类型为空)。");
                // 更新 Debug 消息以反映实际检查
                Debug.WriteLine($"GetOrCreateParameterDefinition 错误: 输入无效 (组: {group == null}, 名称: '{paramName}', 类型: {paramDataTypeSpec?.TypeId ?? "null"})");
                return null;
            }

            // *** 方法的其余部分保持不变 ***
            try
            {
                // 尝试按名称获取现有定义
                Definition definition = group.Definitions.get_Item(paramName);
                ExternalDefinition externalDef = null;

                // 如果定义不存在
                if (definition == null)
                {
                    // 创建选项
                    ExternalDefinitionCreationOptions options = new ExternalDefinitionCreationOptions(paramName, SpecTypeId.String.Text);
                    options.GUID = SharedParameterGuid;
                    options.Visible = true;

                    // 创建定义
                    definition = group.Definitions.Create(options);
                    if (definition == null)
                    {
                        TaskDialog.Show("错误", $"无法创建共享参数定义 '{paramName}'。");
                        Debug.WriteLine($"GetOrCreateParameterDefinition: 创建定义 '{paramName}' 失败。");
                        return null;
                    }
                    externalDef = definition as ExternalDefinition;
                    Debug.WriteLine($"创建了新的共享参数定义: {paramName} (GUID: {externalDef?.GUID}, Type: {externalDef?.GetDataType()?.TypeId})");
                }
                // 如果定义存在且是 ExternalDefinition 类型
                else if (definition is ExternalDefinition extDefCheck)
                {
                    externalDef = extDefCheck;

                    // 检查 GUID
                    if (externalDef.GUID != SharedParameterGuid)
                    {
                        TaskDialog.Show("错误", $"共享参数 '{paramName}' 已存在，但其 GUID ({externalDef.GUID}) 与插件预期的 GUID ({SharedParameterGuid}) 不符。\n\n请检查共享参数文件。");
                        Debug.WriteLine($"GetOrCreateParameterDefinition 错误: GUID 不匹配。现有: {externalDef.GUID}, 预期: {SharedParameterGuid}");
                        return null;
                    }

                    // 检查数据类型
                    ForgeTypeId existingDataType = externalDef.GetDataType();
                    if (existingDataType == null || !existingDataType.Equals(paramDataTypeSpec))
                    {
                        TaskDialog.Show("错误", $"共享参数 '{paramName}' 已存在，但其数据类型 ({existingDataType?.TypeId ?? "未知"}) 与插件预期的数据类型 ({paramDataTypeSpec.TypeId}) 不匹配。\n\n请检查共享参数文件。");
                        Debug.WriteLine($"GetOrCreateParameterDefinition 错误: 数据类型不匹配。现有: {existingDataType?.TypeId ?? "null"}, 预期: {paramDataTypeSpec.TypeId}");
                        return null;
                    }

                    Debug.WriteLine($"共享参数定义 '{paramName}' 已存在且 GUID 和数据类型均匹配。");
                }
                // 如果定义存在但不是 ExternalDefinition 类型
                else
                {
                    TaskDialog.Show("错误", $"名为 '{paramName}' 的参数定义已存在，但它不是外部共享参数。");
                    Debug.WriteLine($"GetOrCreateParameterDefinition 错误: 找到同名定义但类型不是 ExternalDefinition (类型为: {definition?.GetType().Name})");
                    return null;
                }

                return externalDef;
            }
            // 捕获异常
            catch (Exception ex)
            {
                TaskDialog.Show("错误", $"无法获取或创建共享参数定义 '{paramName}':\n{ex.Message}");
                Debug.WriteLine($"GetOrCreateParameterDefinition Exception: {ex}");
                return null;
            }
        }

        /// <summary>
        /// 检查参数是否已作为实例参数绑定到指定的 Revit 类别。
        /// </summary>
        private static bool IsParameterBound(Document doc, ExternalDefinition definition)
        {
            if (doc == null || definition == null)
            {
                Debug.WriteLine($"IsParameterBound 检查跳过: 输入无效 (doc: {doc == null}, definition: {definition == null})");
                return false;
            }
            try
            {
                Category cat = doc.Settings.Categories.get_Item(TargetCategory);
                if (cat == null)
                {
                    Debug.WriteLine($"IsParameterBound 警告: 无法在文档中找到目标类别 '{TargetCategory}'。");
                    return false;
                }
                BindingMap map = doc.ParameterBindings;
                if (map == null)
                {
                    Debug.WriteLine("IsParameterBound 警告: 无法获取文档的参数绑定映射 (BindingMap)。");
                    return false;
                }
                if (map.Contains(definition))
                {
                    ElementBinding binding = map.get_Item(definition) as ElementBinding;
                    if (binding is InstanceBinding instanceBinding && instanceBinding.Categories.Contains(cat))
                    {
                        Debug.WriteLine($"IsParameterBound: 参数 '{definition.Name}' 已确认绑定到类别 '{TargetCategory}'。");
                        return true;
                    }
                }
                Debug.WriteLine($"IsParameterBound: 参数 '{definition.Name}' 未绑定到类别 '{TargetCategory}'。");
                return false;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"IsParameterBound 检查时发生错误: {ex.ToString()}");
                return false;
            }
        }

        /// <summary>
        /// 将共享参数定义作为实例参数绑定到指定类别。
        /// </summary>
        private static bool BindParameterToCategory(Document doc, Application app, ExternalDefinition definition, BuiltInCategory categoryEnum)
        {
            if (doc == null || app == null || definition == null)
            {
                Debug.WriteLine($"BindParameterToCategory 错误: 输入无效 (doc: {doc == null}, app: {app == null}, definition: {definition == null})");
                return false;
            }

            bool success = false;
            using (Transaction trans = new Transaction(doc, $"绑定参数 {definition.Name} 到 {categoryEnum}"))
            {
                try
                {
                    trans.Start();

                    CategorySet cats = app.Create.NewCategorySet();
                    Category cat = doc.Settings.Categories.get_Item(categoryEnum);
                    if (cat == null)
                    {
                        TaskDialog.Show("错误", $"无法在文档中找到类别 '{categoryEnum}'，无法绑定参数。");
                        trans.RollBack();
                        Debug.WriteLine($"BindParameterToCategory 错误: 找不到类别 '{categoryEnum}'。");
                        return false;
                    }
                    cats.Insert(cat);

                    InstanceBinding binding = app.Create.NewInstanceBinding(cats);

                    // 添加检查
                    Debug.WriteLine($"尝试 ReInsert 绑定: definition is null? {definition == null}");
                    Debug.WriteLine($"尝试 ReInsert 绑定: binding is null? {binding == null}");
                    Debug.WriteLine($"尝试 ReInsert 绑定: ParameterGroupInUI = {ParameterGroupInUI}");

                    if (definition == null || binding == null)
                    {
                        TaskDialog.Show("调试错误", "无法插入/重新插入绑定，因为 definition 或 binding 为空。");
                        trans.RollBack();
                        return false;
                    }

                    // ****** 尝试使用 ReInsert ******
                    if (doc.ParameterBindings.ReInsert(definition, binding, ParameterGroupInUI))
                    {
                        success = true;
                        trans.Commit();
                        Debug.WriteLine($"成功将参数 '{definition.Name}' 绑定到类别 '{categoryEnum}' (分组: {ParameterGroupInUI})。");
                    }
                    else
                    {
                        // ReInsert 失败也提示
                        TaskDialog.Show("绑定失败", $"无法将共享参数 '{definition.Name}' 绑定到类别 '{categoryEnum}'。\n\n可能是由于权限问题或冲突。");
                        trans.RollBack();
                        Debug.WriteLine($"BindParameterToCategory: ReInsert 绑定失败。");
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine($"BindParameterToCategory 事务中发生错误: {ex.ToString()}");
                    TaskDialog.Show("错误", $"绑定共享参数 '{definition.Name}' 时出错: {ex.Message}");
                    if (trans.HasStarted() && trans.GetStatus() == TransactionStatus.Started)
                    {
                        trans.RollBack();
                    }
                    success = false;
                }
            } // using 结束

            return success;
        }

    } // End Class SharedParameterHelper
} // End Namespace RevitProject.Helper